# myself:lanfilesearch/app.py
from elasticsearch import Elasticsearch
from elasticsearch.exceptions import NotFoundError
from flask import Flask, request, jsonify, render_template
import json
import os
import logging
from datetime import datetime

app = Flask(__name__)

# Configure logging
log_file = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'app.log')
logging.basicConfig(
    filename=log_file,
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    datefmt='%d/%b/%Y %H:%M:%S'
)

# Initialize Elasticsearch client
es = Elasticsearch(
    hosts="https://localhost:9200",
    api_key="T0lqM2RKWUI4clBKeFVBenFaZGc6MTBWZmU3d3VSX0dHQy1iNjBfbHRyUQ==",
    ca_certs="/srv/elasticsearch-8.12.2/config/certs/http_ca.crt"
)

@app.before_request
def log_request_info():
    app.logger.info(f"Request: {request.method} {request.path} from {request.remote_addr}")

@app.after_request
def log_response_info(response):
    app.logger.info(f"Response: {request.method} {request.path} - Status: {response.status_code}")
    return response

@app.route('/')
def index():
    app.logger.info("Serving index page")
    return render_template('index.html')

@app.route('/api/search/content', methods=['POST'])
def search_content():
    try:
        data = request.json
        query = data.get('query', '')
        size = int(data.get('size', 10))
        scroll_id = data.get('scroll_id')
        
        app.logger.info(f"Content search initiated - Query: {query}, Size: {size}, Scroll ID: {scroll_id or 'None'}")
        
        if scroll_id:
            try:
                response = es.scroll(scroll_id=scroll_id, scroll='30m')
                app.logger.debug(f"Scroll request executed - Scroll ID: {scroll_id}")
            except NotFoundError:
                app.logger.warning(f"Scroll session expired - Scroll ID: {scroll_id}")
                return jsonify({
                    "success": False,
                    "error": "scroll_timeout",
                    "message": "搜索会话已过期，请重新搜索"
                })
        else:
            body = {
                "query": {
                    "bool": {
                        "must": [
                            {
                                "match": {
                                    "content": {
                                        "query": query,
                                        "analyzer": "ik_smart"
                                    }
                                }
                            },
                            {
                                "term": {
                                    "status": "completed"
                                }
                            }
                        ],
                        "must_not": [
                            {
                                "wildcard": {
                                    "primary_file": "/服务器/2.教学部门/0.资源库/*"
                                }
                            }
                        ]
                    }
                },
                "size": size,
                "highlight": {
                    "fields": {
                        "content": {
                            "number_of_fragments": 3,
                            "fragment_size": 100
                        }
                    }
                }
            }
            response = es.search(index="file_hash", body=body, scroll='30m')
            app.logger.debug(f"New search executed - Query: {query}, Index: file_hash")
        
        scroll_id = response['_scroll_id']
        hits = response['hits']['hits']
        app.logger.info(f"Search results found - Total: {response['hits']['total']['value']}, Returned: {len(hits)}")
        
        results = []
        for hit in hits:
            result = hit['_source']
            if 'highlight' in hit:
                result['highlight'] = hit['highlight']
            
            # 直接从file_hash索引获取所有信息，不需要二次查询
            result['modified_date'] = result.get('modified_date')
            result['filename'] = result.get('primary_file', '')
            
            results.append(result)
        
        return jsonify({
            "success": True,
            "total": response['hits']['total']['value'],
            "data": results,
            "scroll_id": scroll_id,
            "has_more": len(hits) > 0
        })
        
    except Exception as e:
        app.logger.error(f"Error in content search: {str(e)}", exc_info=True)
        return jsonify({"success": False, "error": str(e)}), 500

@app.route('/api/search/files', methods=['POST'])
def search_files():
    try:
        data = request.json
        query = data.get('query', '').strip()
        file_type = data.get('file_type', 'all')
        sort_field = data.get('sort_field', 'modified_date')
        sort_order = data.get('sort_order', 'desc')
        from_ = data.get('from', 0)
        size = data.get('size', 10)
        
        app.logger.info(
            f"File search initiated - Query: {query}, File type: {file_type}, "
            f"Sort: {sort_field} {sort_order}, From: {from_}, Size: {size}"
        )
        
        must_clauses = []
        
        if query:
            must_clauses.append({
                "wildcard": {
                    "primary_file": {
                        "value": f"*{query.lower()}*",
                        "case_insensitive": True
                    }
                }
            })
        
        if file_type != 'all':
            # 根据文件类型过滤
            ext_mapping = {
                'word': ['.docx', '.doc'],
                'excel': ['.xlsx', '.xls'],
                'ppt': ['.pptx', '.ppt'],
                'pdf': ['.pdf'],
                'text': ['.txt', '.html', '.htm'],
                'image': ['.jpg', '.jpeg', '.png', '.gif', '.bmp'],
                'audio': ['.mp3', '.wma', '.amr'],
                'video': ['.mp4', '.mov', '.swf']
            }
            
            if file_type in ext_mapping:
                must_clauses.append({
                    "terms": {
                        "file_ext": ext_mapping[file_type]
                    }
                })
        
        body = {
            "query": {
                "bool": {
                    "must": must_clauses,
                }
            },
            "sort": [
                {sort_field: {"order": sort_order}},
                {"primary_file": {"order": "asc"}}
            ],
            "from": from_,
            "size": size
        }
        
        response = es.search(index="file_hash", body=body)
        
        total = response['hits']['total']['value']
        hits = response['hits']['hits']
        app.logger.info(f"File search results - Total: {total}, Returned: {len(hits)}")
        
        results = []
        for hit in hits:
            source = hit['_source']
            duplicate_files = source.get("duplicate_files", [])
            if isinstance(duplicate_files, str):
                # 如果存储的是字符串格式，尝试解析为数组
                try:
                    duplicate_files = json.loads(duplicate_files.replace("'", '"'))
                except:
                    duplicate_files = []
            results.append({
                "md5_hash": source.get("md5_hash", ""),
                "primary_file": source.get("primary_file", ""),
                "duplicate_files": duplicate_files, 
                "file_ext": source.get("file_ext", ""),
                "modified_date": source.get("modified_date"),
                "status": source.get("status", "")
            })
        
        return jsonify({
            "success": True,
            "total": total,
            "data": results
        })
        
    except Exception as e:
        app.logger.error(f"Error in file search: {str(e)}", exc_info=True)
        return jsonify({
            "success": False,
            "error": str(e)
        }), 500

if __name__ == '__main__':
    app.logger.info("Starting Flask application")
    app.run(debug=True, host='0.0.0.0', port=80)